<?php

/**
 * alltosun.com 支付宝控制器 index.php
 * ============================================================================
 * 版权所有 (C) 2009-2014 北京互动阳光科技有限公司，并保留所有权利。
 * 网站地址: http://www.alltosun.com
 * ----------------------------------------------------------------------------
 * 许可声明: 这是一个开源程序，未经许可不得将本软件的整体或任何部分用于商业用途及再发布。
 * ============================================================================
 * $Author: 吴松键 (wusj@alltosun.com) $
 * $Date: 2014-9-25 下午2:09:54 $
 * $Id$
 */

class Action
{
    private $alipay_config;
    private $user_id;
    public function __construct()
    {
        require_once MODULE_PATH.'/openapi/config/alipay_config.php';

        $this->alipay_config = array(
            // @fixed by liw 此三个参数由订单获取
            //'partner'            => Config::get('partner'),
            //'key'                => Config::get('alipay_key'),
            //'seller_email'       => Config::get('seller_email'),
            'input_charset'      => Config::get('input_charset'),
            'transport'          => Config::get('transport'),
            'sign_type'          => Config::get('sign_type'),
            'cacert'             => Config::get('cacert'),
            'alipay_gateway_new' => Config::get('alipay_gateway_new'),
        );
        $this->user_id = user_helper::get_user_id();
    }

    /**
     * 付款
     */
    public function pay()
    {
        $order_id = Request::getParam('order_id', 0);
        if (!$this->user_id) {
            return array('请登陆后进行操作', 'error', AnUrl('user/login'));
        }
        if (is_mobile()) {
            Response::redirect(AnUrl('openapi/alipay/m/pay?order_id='.$order_id));
            Response::flush();
            exit;
        }

        if ($order_id > 0) {

            $order_info = _uri('order', $order_id);
            if($order_info['user_id'] != $this->user_id) {
                return array('您的订单有误，请重新发起支付', 'error', AnUrl('order'));
            }
            if (!$order_info || $order_info['id'] < 1) {
                return array('支付超时，请重新发起支付', 'error', AnUrl('order'));
            }
            if ($order_info['progress'] > 1) {
                return array('支付超时，请重新发起支付', 'error', AnUrl('order'));
            }

            // 重置支付方式 add by liw
            $this->alipay_config = array_merge($this->alipay_config, openapi_helper::get_order_pay_account($order_id));

            if (ONDEV) {
                $total_fee = 0.01;
            } else {
                $total_fee = $order_info['price'];
            }

            $order_args = array(
                "service"           => "create_direct_pay_by_user",
                "partner"           => trim($this->alipay_config['partner']),          // 合作身份者ID
                "payment_type"      => 1,
                "notify_url"        => AnUrl('openapi/alipay/index/pay_notify'),       // 后台回调URL
                "return_url"        => AnUrl('openapi/alipay/index/pay_return'),       // 前台回调URL
                "seller_email"      => $this->alipay_config['seller_email'],           // 商家账号
                "out_trade_no"      => order_helper::order_id_encode($order_id, 1),    // 订单编号
                "subject"           => order_helper::get_goods_title($order_id),    // 商品名称
                "total_fee"         => $total_fee,                                  // 订单总价
                "body"              => '',                                          // 商品描述
                "show_url"          => '',                                          // 商品URL
                "anti_phishing_key" => '',                                          // 防钓鱼，需要服务器支持DOM
                "exter_invoke_ip"   => get_ip(),                     // 用户ip
                "_input_charset"    => trim(strtolower($this->alipay_config['input_charset'])), // 字符集
            );

            $param_string = $this->build_request_param_string($order_args); // 生成支付参数

            Response::redirect($this->alipay_config['alipay_gateway_new'].$param_string);
        } else {
            return array('支付超时，请重新发起支付', 'error', AnUrl('order'));
        }
    }

    public function refund()
    {
        // @todo 只支持单个退款
        $refund_id = Request::getParam('refund_id', 0);
        if (!$this->user_id) {
            return array('请登陆后进行操作', 'error', AnUrl('user/login'));
        }
        if (!$refund_id) {
            return '请选择需要退款的订单';
        }

        $refund_id = explode(',', $refund_id);
        $detail_data = array();
        $batch_num = count($refund_id);
        $batch_no = date('YmdHis').'newbdrefund'.$batch_num;
        foreach ($refund_id as $k=>$v) {
            $refund_info = _uri('refund', $v);
            if (!$refund_info || empty($refund_info)) {
                return '请选择需要退款的订单';
            }
            //add zhangyh 150710
            if($refund_info['refund_status'] == 20) {
                return '此退货单已经退过款了。';
            }
            $order_info = _uri('order', $refund_info['order_id']);

            // 同一时间只处理一个退款请求
            //$refund_batch_info = _model('refund_batch')->read(array('refund_id'=>$v, 'transaction_id'=>$order_info['transaction_id'], 'type'=>0));
            //if ($refund_batch_info) {
            //    continue;
            //}
            if (!$order_info) {
                return '当前退款信息有误';
            }



            //...重置支付宝帐号
            $this->alipay_config = array_merge($this->alipay_config, openapi_helper::get_order_pay_account($order_info['id']));

            $detail_data[] = $order_info['transaction_id'].'^'.$refund_info['real_price'].'^'.'协商退款';

            _model('refund')->update(array('id'=>$v), array('refund_pay_status'=>1, 'refund_status'=>15, 'refund_time'=>date('Y-m-d H:i:s')));
            _model('refund_batch')->create(array('refund_id'=>$v, 'transaction_id'=>$order_info['transaction_id'], 'batch_no'=>$batch_no));
        }

        //构造要请求的参数数组
        $parameter = array(
            "service"        => "refund_fastpay_by_platform_pwd",
            "partner"        => trim($this->alipay_config['partner']),
            "notify_url"     => AnUrl('openapi/alipay/refund_notify'),
            "seller_email"   => $this->alipay_config['seller_email'],
            "refund_date"    => date('Y-m-d H:i:s', time()),
            "batch_no"       => $batch_no,  // 退款批次号
            "batch_num"      => $batch_num,
            "detail_data"    => join('$', $detail_data),
            "_input_charset" => trim(strtolower($this->alipay_config['input_charset']))
        );

        $param_string = $this->build_request_param_string($parameter); // 生成退款参数

        Response::redirect($this->alipay_config['alipay_gateway_new'].$param_string);
    }

    public function refund_test()
    {
        if(!ONDEV) {
            throw new AnMessageException('ACCESS FORBIDDEN');
        }
        $refund_id = Request::getParam('refund_id', 0);

        $refund_info = _uri('refund', $refund_id);
        if ($refund_info['refund_status'] == 15) {
            $transaction_id = date('YmdHis').rand(1, 999999999);
            $update = _model('refund')->update($refund_id, array('refund_status'=>20, 'transaction_id'=>$transaction_id, 'refunded_time'=>date('Y-m-d H:i:s')));

            $info = _widget('erp_lenovo.erp_lenovo_order')->AddREOrder($refund_id);
            if ($info) {
                var_dump($info);
            }
        }
    }

    /**
     * 退款异步通知
     */
    public function refund_notify()
    {
        require_once MODULE_PATH.'/openapi/helper/alipay/alipay_notify.class.php';
        try{

            $batch_no       = Request::Post('batch_no');       // 退款批次号
            $success_num    = Request::Post('success_num');    // 退款成功数量
            $result_details = Request::Post('result_details'); // 退款详情
            $refund_details = explode('$', $result_details);
            $batch_num      = _model('refund_batch')->getTotal(array('batch_no'=>$batch_no));

            if(!$batch_no || !$result_details) {
                throw new Exception('通知参数为空：$batch_no or $result_details');
            }

            if($success_num >= 0 && $success_num <= $batch_num) {
                foreach ($refund_details as $k=>$v) {
                    $transaction_info = explode('^', $v);
                    $refund_batch_info = _model('refund_batch')->read(array('batch_no'=>$batch_no, 'transaction_id'=>$transaction_info[0]));
                    $refund_info    = _uri('refund', $refund_batch_info['refund_id']);
                    $order_info     = _uri('order', $refund_info['order_id']);

                    if(!$refund_batch_info || !$refund_info || !$order_info) {
                        throw new Exception('未获取到资源信息：$refund_batch_info or $refund_info or $order_info');
                    }

                    // 重置支付宝配置 liw add
                    $this->alipay_config = array_merge($this->alipay_config, openapi_helper::get_order_pay_account($order_info['id']));
                    // 验证传值
                    $alipayNotify  = new AlipayNotify($this->alipay_config);
                    $verify_result = $alipayNotify->verifyNotify();
                    if(!$verify_result) {
                        throw new Exception("后台通知链接错误！");
                    }

                    if ($refund_info['refund_status'] != 15 && $refund_info['refund_pay_status'] != 1) {
                        $ret_msg = "当前退款状态有误";
                    } else {
                        $ret_msg = '支付宝退款成功,此通知为异步通知';
                        $info = array(
                            'transaction_id' => $batch_no,
                            'refund_status'  => 20,
                            'refund_pay_status' => 2,
                            'refunded_time'     => date('Y-m-d H:i:s')
                        );

                        if ($transaction_info[2] != 'SUCCESS') {
                            $info['refund_status'] = 23;
                            $info['refund_pay_status'] = 3;
                            $ret_msg = '支付宝退款失败，错误代码：'.$transaction_info[2];
                        }

                        _model('refund_batch')->update(array('id'=>$refund_batch_info['id']), array('type'=>1));
                        _model('refund')->update($refund_info['id'], $info);

                        //返还销量
                        order_helper::refund_sale_num($order_id);
                        //返回库存
                        order_helper::refund_stock($order_id);
                        $info = _widget('erp_lenovo.erp_lenovo_order')->AddREOrder($refund_info['id']);

                        // 发送退款完成短信
                        $email = _uri('user', $order_info['user_id'], 'email');
                        order_helper::sendExpressMessage('refund_success', array(order_helper::order_id_encode($order_info['id'])), $order_info['mobile'], $email);
                    }

                    log_helper::create_refund_log('alipay', array(
                        'transaction_id' => $order_info['transaction_id'],
                        'order_id'       => $order_info['id'],
                        'refund_id'      => $refund_batch_info['refund_id'],
                        'transaction_refund_id' => $batch_no,
                        'refund_fee'     => $refund_info['real_price'],
                        'refund_status'  => 'success',
                        'ret_msg'        => $ret_msg
                    ));
                }
            } else {
                throw new Exception($result_details);
            }

            exit('success');
        } catch(Exception $exp) {
            log_helper::create_refund_log('alipay', array(
                'transaction_id' => '',
                'order_id'       => '',
                'refund_id'      => '',
                'transaction_refund_id' => '',
                'refund_fee'     => '',
                'refund_status'  => 'error',
                'ret_msg'        => '支付宝退款失败:'.var_export($exp, true)
            ));

            exit('fail');
        }
    }

    /**
     * 支付同步通知
     */
    public function pay_return()
    {
        require_once MODULE_PATH.'/openapi/helper/alipay/alipay_notify.class.php';
        try{

            $out_trade_no = $_GET['out_trade_no'];   // 商户订单号
            $trade_no     = $_GET['trade_no'];           // 支付宝交易号
            $trade_status = $_GET['trade_status'];   // 交易状态

            if ($out_trade_no) {
                $order_id = order_helper::order_id_decode($out_trade_no);
                $order_id = (int)$order_id;
                if(!$order_id) {
                    throw new Exception("订单不存在");
                }
                $order_info = _uri('order', (int)$order_id);

                $this->alipay_config = array_merge($this->alipay_config, openapi_helper::get_order_pay_account($order_id));
                $alipayNotify  = new AlipayNotify($this->alipay_config);
                $verify_result = $alipayNotify->verifyReturn();
                if(!$verify_result) {
                    throw new Exception("响应时间过期");
                }

                if ($order_info['progress'] == 10) {
                    return array('交易成功，等待商家发货！', 'error', AnUrl('order'));
                } else {
                    return array('交易处理中，请耐心等待', 'error', AnUrl('order'));
                }
            } elseif ($trade_status == 'TRADE_CLOSED') {
                throw new Exception("当前交易被关闭！");
            }

            return array('交易处理中，请耐心等待', 'error', AnUrl('order'));
        } catch(Exception $exp) {
            log_helper::create_pay_log('alipay', array(
                'transaction_id' => '',
                'order_id'       => '',
                'total_price'    => '',
                'trade_status'   => 'error',
                'remarks'        => '支付宝支付失败:'.$exp->getMessage()
            ));

            return array($exp->getMessage(), 'error', AnUrl('order'));
        }
    }

    /**
     * 支付异步通知
     */
    public function pay_notify()
    {
        require_once MODULE_PATH.'/openapi/helper/alipay/alipay_notify.class.php';
        try{
            $out_trade_no = Request::Post('out_trade_no');   //商户订单号
            $trade_no     = Request::Post('trade_no');       //支付宝交易号
            $trade_status = Request::Post('trade_status');   //交易状态
            $total_price  = Request::Post('total_fee');      // 付款金额

            if($trade_status == 'TRADE_FINISHED' || $trade_status == 'TRADE_SUCCESS') {
                $order_id = order_helper::order_id_decode($out_trade_no);
                $order_id = (int)$order_id;
                if(!$order_id) {
                    throw new Exception("订单不存在");
                }
                $order_info = _uri('order', $order_id);
                $info['progress'] = 10;
                $info['transaction_id'] = $trade_no;
                $info['pay_time'] = date('Y-m-d H:i:s', time());

                $this->alipay_config = array_merge($this->alipay_config, openapi_helper::get_order_pay_account($order_id));
                $alipayNotify  = new AlipayNotify($this->alipay_config);
                $verify_result = $alipayNotify->verifyNotify();
                if(!$verify_result) {
                    throw new Exception("后台通知链接错误！");
                }

                if ($order_info['progress'] == 1 ) {
                    _model('order')->update(array('id'=>$order_id), $info);
                    //增加销量
                    order_helper::add_sale_num($order_id);
                    _widget('erp_lenovo.erp_lenovo_order')->AddOrder($order_id);
                    $mobile = Config::get('admin_mobile');
                    if ($mobile) {
                        order_helper::sendExpressMessage('pay_success', array(order_helper::order_id_encode($order_id)), $mobile);
                    }
                }
            } elseif ($trade_status == 'TRADE_CLOSED') {
                throw new Exception("当前交易被关闭！");
            }

            log_helper::create_pay_log('alipay', array(
                'transaction_id' => $trade_no,
                'order_id'       => order_helper::order_id_decode($out_trade_no),
                'total_price'    => $total_price,
                'trade_status'   => 'success',
                'remarks'        => '支付成功，当前通知为异步通知'
            ));

            echo 'success';
        } catch(Exception $exp) {
            log_helper::create_pay_log('alipay', array(
                'transaction_id' => '',
                'order_id'       => '',
                'total_price'    => '',
                'trade_status'   => 'error',
                'remarks'        => '支付宝支付失败:'.$exp->getMessage()
            ));
            echo 'fail';
        }
    }

    /**
     * 生成要请求给支付宝的参数数组
     * @param $para_temp 请求前的参数数组
     * @return 要请求的参数数组字符串
     */
    private function build_request_param_string($param_temp) {
        //待请求参数数组
        $param_filter = openapi_helper::param_filter($param_temp);

        //对待签名参数数组排序
        $param_sort = openapi_helper::param_sort($param_filter);

        //生成签名结果
        $mysign = openapi_helper::build_request_sign($param_sort, $this->alipay_config['key'], 'alipay');

        //签名结果与签名方式加入请求提交参数组中
        $param_sort['sign']      = $mysign;
        $param_sort['sign_type'] = strtoupper(trim($this->alipay_config['sign_type']));

        //把参数组中所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串，并对字符串做urlencode编码
        $request_data = http_build_query($param_sort);

        return $request_data;
    }
}
?>